package com.zuoban.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zuoban.common.Result;
import com.zuoban.constant.HttpStatus;
import com.zuoban.dto.UserLoginDto;
import com.zuoban.entity.base.BaseUserInfo;
import com.zuoban.log.Subject;
import com.zuoban.mapper.BaseUserInfoMapper;
import com.zuoban.service.BaseUserInfoService;
import com.zuoban.service.strategy.LoginStrategyService;
import com.zuoban.util.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigInteger;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @BelongsProject: zuoban-boot
 * @BelongsPackage: com.zuoban.service.impl
 * @Author: zxy
 * @CreateTime: 2022-10-10
 * @Description: ...
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BaseUserInfoServiceImpl implements BaseUserInfoService {

    private final Snowflake snowflake;
    private final RedisUtil redisUtil;
    private final BaseUserInfoMapper baseUserInfoMapper;
    private final Map<String,LoginStrategyService> loginStrategyServiceMap;
    private final ExecutorService executors = Executors.newCachedThreadPool();

    @Override
    public Result login(HttpServletRequest request, UserLoginDto userLoginDto) {
        // 根据前端传的登录策略 实现自动匹配登录方式
        if (!loginStrategyServiceMap.containsKey(userLoginDto.getStrategy())){
            log.error("此次执行策略名称：【"+userLoginDto.getStrategy()+"】,策略编码：【"+userLoginDto.getLoginCode()+"】未找到");
            throw new RuntimeException("未找到该执行策略，请检查后重新登录");
        }
        LoginStrategyService loginStrategyService = loginStrategyServiceMap.get(userLoginDto.getStrategy());
        // 校验编码和策略是否匹配 不匹配则不允许执行通过
        loginStrategyService.checkLoginCode(userLoginDto.getStrategy(), userLoginDto.getLoginCode());
        return loginStrategyService.doLogin(request,userLoginDto);
    }

    @Override
    public Result register(UserLoginDto userLoginDto) {
        /*
          注册逻辑
           1、校验验证码
           2、校验账户同名
           3、密码md5加密
         */
        Result result = null;
        String code = (String) redisUtil.get("ImgCode|"+userLoginDto.getUserAccount());
        if (!Objects.isNull(userLoginDto.getCode()) && !userLoginDto.getCode().equals(code)){
            result = new Result(HttpStatus.HTTP_NO_CONTENT,"验证码不正确，请检查后重新输入",null);
       }else {
            QueryWrapper<BaseUserInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("user_account",userLoginDto.getUserAccount());
            BaseUserInfo baseUserinfo = baseUserInfoMapper.selectOne(wrapper);
            if (!Objects.isNull(baseUserinfo)){
                result = new Result(com.zuoban.constant.HttpStatus.ACCOUNT_EXIST,"该账户名已被注册了哦！",null);
            }else {
                // 不重复 对密码进行加密后新增
                String secPwd = SecureUtil.md5(userLoginDto.getUserPwd());
                String userId = String.valueOf(snowflake.nextId());
                BaseUserInfo userinfo = new BaseUserInfo(new BigInteger(userId), userLoginDto.getUserAccount(), secPwd,null);
                baseUserInfoMapper.insert(userinfo);
                result = Result.success(userinfo);
                // 完成后删除redis中存在的key
                executors.submit(()->{
                    redisUtil.del("ImgCode|"+userLoginDto.getUserAccount());
                });
            }
        }
        return result;
    }

    @SneakyThrows
    @Override
    public void getImgCode(String userAccount, HttpServletResponse response) {
        // 这里用图片验证码做测试 具体业务可以用手机号发短信获取验证码 视情况而定
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        lineCaptcha.setGenerator(randomGenerator);
        lineCaptcha.createCode();
       log.info("用户：【"+userAccount+"】本次登录的验证码为："+lineCaptcha.getCode());
        // 保存redis  一分钟有效
        redisUtil.set("ImgCode|"+userAccount,lineCaptcha.getCode(),120);
        lineCaptcha.write(response.getOutputStream());
    }

    @Override
    public void logout(UserLoginDto userLoginDto) {
        // 清空db中和redis中存储的token即为退出登录
        baseUserInfoMapper.updateToken(userLoginDto.getUserId(),"");
    }
}
